package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

/*本类用于ArrayList的相关测试*/
public class TestArrayList {
    public static void main(String[] args) {
        //1.创建对应的集合对象
        /*底层会自动帮我们创建数组来存放对象,并且数组的初始容量是10*///底层使用数组保存对象,数组初始值容量10,但是可以规定条件下的扩容
        ArrayList<Integer> list = new ArrayList<>();
//        LinkedList<Integer> list = new LinkedList<>();

        //2.向集合中添加元素,用于测试
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(400);
        list.add(400);
        list.add(300);
//        list.add(200);
//        list.add(300);
//        list.add(400);
//        list.add(400);
//        list.add(300);
        System.out.println(list);

        //3.测试常用方法
        //list.clear();//清空集合
        //System.out.println(list);//[]

        //false,是否包含指定元素"100",不包含,这是String,不是Integer
        System.out.println(list.contains("100")); //false "100"是字符串,String
        System.out.println(list.contains(100)); //true
        System.out.println(list.get(0));//100
        System.out.println(list.indexOf(400));//3,判断元素第1次出现的下标
        System.out.println(list.lastIndexOf(400));//4,判断元素最后1次出现的下标
//        System.out.println(list.remove(300));//会报错 .IndexOutOfBoundsException
        /*上面的代码会报错:数组下标越界:index:300 size:6
         * 主要是因为List中有两个重载的remove(),如果传入的是300
         * 会直接把这个300看作是int类型的index索引,所以如果想指定元素来删除数据
         * 需要把int类型的300手动装箱成Integer类型的300元素*/
        System.out.println(list);
        System.out.println(list.remove(Integer.valueOf(300)));//只是删除第一个指定的具体元素的值:remove方法里面包含 , 将int类型数据包含在remove(Integer.valueOf(int))
        //Integer i2 = Integer.valueOf(127); //1)自动装箱Integer高效创建方式: Integer, 2)valueOf, 3)-128~127
        //valueOf返回包装类型,Integer

        System.out.println("after Integer.valueof:"+list);
        System.out.println(list.remove(2));//根据下标删除元素
        System.out.println("list集合:"+list);

        System.out.println(list.set(2,777));//修改指定位置处的元素为777
        System.out.println(list.size());//4,获取集合中的元素个数
        System.out.println(list);
        //测试集合间的操作
        ArrayList<Integer> list2 = new ArrayList<>();
//        new LinkedList<>();
        list2.add(1);
        list2.add(0, 2);
        list2.add(3);
        list2.add(4);
        System.out.println("list2元素:"+list2);

        list.addAll(list2);//将list2集合中的所有元素添加到list集合的末尾
        //list: [100, 200, 777, 300, 1, 2, 3, 4]
        //list2: [1, 2, 3, 4]

        System.out.println(list);//[100, 200, 777, 300, 1, 2, 3, 4]
        //list: [100, 200, 777, 300, 1, 2, 3, 4]
        //list2: [1, 2, 3, 4]
        list.addAll(0,list2);//将list2集合中的所有元素从list集合的0号位置开始添加
        //list: [1, 2, 3, 4,100, 200, 777, 300, 1, 2, 3, 4]
        //list2: [1, 2, 3, 4]

        System.out.println("list+list2:"+list);//[1, 2, 3, 4, 100, 200, 777, 300, 1, 2, 3, 4]
        //list: [1, 2, 3, 4,100, 200, 777, 300, 1, 2, 3, 4]
        //list2: [1, 2, 3, 4]

        list.add(3);
        System.out.println("额外添加单个元素:"+list);
        //list: [1, 2, 3, 4,100, 200, 777, 300, 1, 2, 3, 4,3]
        //list2: [1, 2, 3, 4]
        list.removeAll(list2);//删除list集合中所有属于list2集合的元素,有几个集合就删除几个集合,在list集合里面将list2集合里面所有的元素都排除,直到所有的list2里面任何元素都被排除掉,无论重复还是单个,都被剔除,,
        System.out.println("删除list2后的list集合:"+list);//[100, 200, 777, 300]
        //list: [100, 200, 777, 300]
        //list2: [1, 2, 3, 4]


        //false,判断list集合是否包含list2集合中的所有元素
        list.add(1);
        System.out.println(list2);// list2:[1, 2, 3, 4]
        System.out.println("list添加了元素:"+list); // list添加了元素:[100, 200, 777, 300, 1]
        // list: [100, 200, 777, 300,1]
        // list2:[1, 2, 3, 4]
        //
        //



        list.add(4);
        list.add(3);
        list.add(2);
        list.add(1);
        System.out.println("添加额外元素:"+list);
        // list: [100, 200, 777, 300, 1, 4, 3, 2, 1]
        // list2:[1, 2, 3, 4]
        System.out.println(list.containsAll(list2));//false done //list里面需要有全部list2的元素才能起作用


        System.out.println(list.contains(1));//true done

        ArrayList<Integer> list3 = new ArrayList();
        list3.add(1);
        System.out.println("list3:"+list3);
        // list: [100, 200, 777, 300, 1, 4, 3, 2, 1]
        // list2:[1, 2, 3, 4]
        // list3:[1]

        list.addAll(list3);
        System.out.println("添加list3的List:"+list);
        // list: [100, 200, 777, 300, 1, 4, 3, 2, 1,1]
        // list2:[1, 2, 3, 4]
        // list3:[1]
        System.out.println("list2:"+list2);
        // list: [100, 200, 777, 300, 1, 4, 3, 2, 1,1]
        // list2:[1, 2, 3, 4]
        // list3:[1]

        list.removeAll(list3);
        System.out.println("删除了所有个数(2个)list3集合的list集合:"+list);
        // list: [100, 200, 777, 300, 4, 3, 2]
        // list2:[1, 2, 3, 4]
        // list3:[1]
        list.addAll(list3);
        // list: [100, 200, 777, 300, 4, 3, 2,1]
        // list2:[1, 2, 3, 4]
        // list3:[1]

        list.add(2);
        // list: [100, 200, 777, 300, 4, 3, 2, 1, 2]
        // list2:[1, 2, 3, 4]
        // list3:[1]

        list.retainAll(list2);//取交集,保留list中属于list2的所有元素,两个集合相同的元素
        System.out.println(list);//[1,2]
        System.out.println(list2);
        System.out.println(list3);
        // list: [4, 3, 2, 1, 2]
        // list2:[1, 2, 3, 4]
        // list3:[1]

        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);

        System.out.println(list);
        // list: [4, 3, 2, 1, 2,5,6,7,8,9]
        // list2:[1, 2, 3, 4]
        // list3:[1]
        //测试集合的迭代
        /*1.for循环
          2.高效for循环
          3.iterator
          4.listIterator*/
        //方式1:因为List集合是有序的,元素是有下标的,所以可以根据下标进行遍历
        //从哪开始:0 到哪结束:list.size()-1 如何变化++
        for (int i = 0; i <= list.size()-1; i++) {
            //根据本轮循环遍历到的索引值获取对应位置上的元素
            System.out.println(list.get(i));
        }
        System.out.println("********方式1********");
        //方式2:因为普通for循环遍历效率低,语法复杂,所以使用高效for循环来遍历
        //格式:for(每轮遍历到的元素的类型 元素名 : 要遍历的元素){循环体}
        for(Integer n : list){
            System.out.println(n);
        }
        System.out.println("********方式2********");
        //方式3:从父接口Collection中继承过来的迭代器
        //1.获取要迭代集合对应的迭代器
        Iterator<Integer> it = list.iterator();//外面主函数里面定义创建迭代对象//迭代器里面api默认指定只能添加Integer数据
        //2.通过迭代器判断是否有下一个元素可以迭代
        while(it.hasNext()){ //还有谁?
            //3.通过迭代器获取本轮迭代到的元素
            System.out.println(it.next()); //使用谁!
        }
        System.out.println("********方式3********");
        /*方式4:ListIterator属于List接口独有的迭代器
         * Iterator<E> -- 父接口--hasNext() next() //可以
         * ListIterator<E> -- 子接口--可以使用父接口的功能,除了父接口的功能之外
         * 还有自己特有的功能,比如逆序遍历,添加元素等,但注意,不常用
         * public interface ListIterator<E> extends Iterator<E>
         * */
        ListIterator<Integer> it2 = list.listIterator(); //迭代器里面可以传入Integer包装类型的数据
        //Iterator和list的输入泛型数据要保持一致
        while(it2.hasNext()){
            System.out.println(it2.next());
        }
        System.out.println("********方式4********");


        System.out.println("listIterator的逆序遍历：");     //先正序遍历到最后一个元素,,,然后再从最后一个元素倒序遍历回来,先正序遍历到最后一个元素,,,然后再从最后一个元素倒序遍历回来,先正序遍历到最后一个元素,,,然后再从最后一个元素倒序遍历回来,先正序遍历到最后一个元素,,,然后再从最后一个元素倒序遍历回来,//高度契合和trust的精密分工,自己
        ListIterator<Integer> it3 = list.listIterator();
        while(it3.hasNext()){//判断是否有下一个元素可迭代  //it3.hasNext(), 从第一个开始,1)然后调用方法,2)返回boolean,3)//如果自由3个数,第四个数判断为false不适用了
            //it3.hasNext() 逐个元素判断,判断是否有下一个元素可迭代,从下标o开始,,,

            System.out.println(it3.next());//打印当前迭代到的元素    //中间有一写natva C++ 源码设计, java是一个引导,提示
            /**it3.hasNext()  it3.next()
             * it3(1)  T      it3(1)
             * it3(2)  T      it3(2)
             * it3(3)  T      it3(3)  //地层处理
             * it3(4)  F
             *
             *           !it3.hasNext()
             *
             * */

            if(!it3.hasNext()){//直到迭代器没有下一个元素可迭代--到最后了 // 如果四个数, 第四个空的数字,判断hasNext为False, !it3.hasNext()为true
                // it3.hasNext() 最后一位时 假
                // !it3.hasNext() 最后一位时 真 -->然后判断是否有上一位数,以及打印上一位数

                System.out.println("开始逆序迭代：");
                while (it3.hasPrevious()){//判断是否有上一个元素可迭代  //有坑,从第一个开始,  //从没有值的第四个开始
                    System.out.println(it3.previous());//打印获取到的上一个元素
                }
                break;//终止循环，不然会一直从头到尾，再从尾到头迭代
            }
        }
        System.out.println("********方式5********");
    }
}









